package com.handpay.nocardpay.baselibrary.utils;

import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;

import com.handpay.nocardpay.baselibrary.commbase.BaseProtocolKey;
import com.handpay.nocardpay.baselibrary.logutils.HPLog;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yanglun E-mail:sunshine_yangl@sina.com
 * @version 2015-11-4 下午2:25:27
 */
public class BitmapLoaderNew {
    private static Map<String, String> map = new ConcurrentHashMap<String, String>();
    private static BitmapLoaderNew mInstance;

    public static BitmapLoaderNew getInstance(Context context) {
        if (null == mInstance) {
            mInstance = new BitmapLoaderNew();
            ImageLoaderConfiguration configuration = ImageLoaderConfiguration
                    .createDefault(context);
            ImageLoader.getInstance().init(configuration);

        }
        return mInstance;
    }

    public void loadImage(String uri, ImageView iv) {

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                // .showImageOnLoading(R.drawable.ic_stub) //加载图片时的图片
                // .showImageForEmptyUri(R.drawable.ic_empty) //没有图片资源时的默认图片
                // .showImageOnFail(R.drawable.ic_error) //加载失败时的图片
                .cacheInMemory(true) // 启用内存缓存
                .cacheOnDisk(true) // 启用外存缓存
                .considerExifParams(true) // 启用EXIF和JPEG图像格式
                // .displayer(new RoundedBitmapDisplayer(20)) //设置显示风格这里是圆角矩形
                .build();
        ImageLoader.getInstance().displayImage(uri, iv, options);
    }

    public void loadImage(String uri, BitmapLoaderListener listener) {

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .cacheInMemory(true) // 启用内存缓存
                .cacheOnDisk(true) // 启用外存缓存
                .considerExifParams(true) // 启用EXIF和JPEG图像格式
                .build();
//		ImageLoader.getInstance().displayImage(uri, iv, options,listener);

        ImageLoader.getInstance().loadImage(uri, options, listener);
    }

    /**
     * 加载图片（带进度条）
     *
     * @param uri
     * @param width
     * @param height
     * @param listener
     * @param progressListener
     */
    public void loadImage(String uri, int width, int height, BitmapLoaderListener listener, ImageLoadingProgressListener progressListener) {
        ImageSize imageSize = new ImageSize(width, height);
        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .cacheInMemory(true) // 启用内存缓存
                .cacheOnDisk(true) // 启用外存缓存
                .considerExifParams(true) // 启用EXIF和JPEG图像格式
                .build();
        ImageLoader.getInstance().loadImage(uri, imageSize, options, listener, progressListener);
    }


    abstract static public class BitmapLoaderListener implements
            ImageLoadingListener {
        @Override
        public void onLoadingStarted(String imageUri, View view) {

        }

        @Override
        public void onLoadingFailed(String imageUri, View view,
                                    FailReason failReason) {

        }

        @Override
        public void onLoadingCancelled(String imageUri, View view) {

        }
    }

    /**
     * 这是个耗时操作。如果需要异步回调，请调用asynLoadBitmap这个方法。
     *
     * @param userName
     * @param imageUrl
     * @return
     */
    public Bitmap loadBitmap(Context context, String userName, String imageUrl) {
        final BitmapCacheUtils bcu = BitmapCacheUtils.getInstance();
        if (bcu.isInCache(userName)) {
            // 从缓存中获取
            Bitmap drawable = bcu.getBitmap(userName);
            if (null != drawable) {
                return drawable;
            }
        }
        Bitmap bitmap;
        if (imageUrl.startsWith("content")) {
            bitmap = loadImageFromUri(context, imageUrl);
        } else {
            bitmap = loadImageFromUrl(imageUrl, true);
        }
        if (null != bitmap) {
            bcu.putInCache(userName, bitmap);
        }
        return bitmap;
    }

    private Bitmap loadImageFromUri(Context context, String uri) {
        InputStream i = null;
        try {
            ContentResolver cr = context.getContentResolver();
            i = cr.openInputStream(Uri.parse(uri));
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            Rect outPadding = new Rect();
            BitmapFactory.decodeStream(i, outPadding, options);
            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, BaseProtocolKey.MAX_PX_LENGTH, BaseProtocolKey.MAX_PX_LENGTH);
            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            i.close();
            HPLog.i("loadImageFromUri", options.inSampleSize);
            i = cr.openInputStream(Uri.parse(uri));
            return BitmapFactory.decodeStream(i, outPadding, options);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != i) {
                    i.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private Bitmap loadImageFromUrl(String uri, boolean isCache) {
        URL m;
        InputStream i = null;
        // yanglun2 get map
        String u = getUri(uri);

        // 如果找到了，替换
        if (!TextUtils.isEmpty(u)) {
            // 修复重复下载的bug。TODO: cache应该放在数据库，或存在硬盘，否则重新启动应用，还是会重复下载
            File file = new File(URI.create(u));
            if (!isCache || !file.exists()) {
                map.remove(uri);
            } else {
                uri = u;
            }
        }
        try {
            // 如果是网络请求，先保存到本地。
            if (uri.startsWith("http")) {
                u = trySaveFile(uri);
                if (!TextUtils.isEmpty(u)) {
                    uri = u;
                } else {
                    // 如果访问不了，返回Bitmap为空
                    return null;
                }
            }
            // 剩下的应该就是访问本地文件了。
            HPLog.i("loadImageFromUrl", "pre2 uri:" + uri);
            m = new URL(uri);
            i = (InputStream) m.getContent();
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            Rect outPadding = new Rect();
            HPLog.i("time", "before get option:" + uri);
            BitmapFactory.decodeStream(i, outPadding, options);
            HPLog.i("time", "after get option:" + uri);
            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options,
                    BaseProtocolKey.MAX_PX_LENGTH, BaseProtocolKey.MAX_PX_LENGTH);
            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            i.close();
            i = (InputStream) m.getContent();
            HPLog.i("loadImageFromUri", options.inSampleSize);
            HPLog.i("time", "before decode" + uri);
            Bitmap b = BitmapFactory.decodeStream(i, outPadding, options);
            HPLog.i("time", "after decode" + uri);
            return b;
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != i) {
                    i.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private static String getUri(String uri) {
        if (TextUtils.isEmpty(uri)) {
            return null;
        }
        return map.get(uri);
    }

    /**
     * @param uri 访问网络的uri。
     * @return 如果成功保存到本地，返回本地的位置；访问不了uri，返回为null; 其他情况返回uri本身
     */
    private static String trySaveFile(String uri) {
        URL m;
        InputStream i;
        try {
            m = new URL(uri);
            i = (InputStream) m.getContent();
        } catch (MalformedURLException me) {
            HPLog.e("CommonUtils", "loadImageFromUrl", me);
            return null;
        } catch (IOException ioe) {
            HPLog.e("CommonUtils", "loadImageFromUrl", ioe);
            return null;
        }
        int startIndex = uri.lastIndexOf("/");
        String strFileName = uri.substring(startIndex);
        // File f = CommonUtils.randomFile(CommonUtils.getAccessDir());
        File f = CommonUtils.getAutoExistFile(CommonUtils.getAccessDir(), strFileName);
        // FIXME 如果如果从网络没有读取到任何数据呢？或404呢？也会存的吧！
        try {

            if (f.createNewFile()) {
                BufferedOutputStream bos = null;
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(f));
                    byte[] array = new byte[1024];
                    int length;
                    while (0 < (length = i.read(array, 0, 1024))) {
                        bos.write(array, 0, length);
                        Arrays.fill(array, (byte) 0);
                    }
                    // 成功保存在本地之后，做映射。
                    Uri u = Uri.fromFile(f);
                    map.put(uri, u.toString());
                    uri = u.toString();
                } catch (IOException ioe) {
                    HPLog.e("CommonUtils", "loadImageFromUrl", ioe);
                    // 如果出现异常。删除掉这个文件。
                    f.delete();
                } finally {
                    if (null != bos) {
                        bos.close();
                    }
                    if (null != i) {
                        i.close();
                    }
                }
            }
        } catch (IOException ioe) {
            HPLog.e("CommonUtils", "loadImageFromUrl", ioe);
        }
        return uri;
    }

    private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height;
            final int halfWidth = width;
            // Calculate the largest inSampleSize value that is a power of 2 and
            // keeps both
            // height and with larger than the requested height and with.
            while ((halfHeight / inSampleSize) > reqHeight
                    || (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

    public byte[] loadBitmapNoCompress(String uri) {
        URL m;
        InputStream i;
        try {
            m = new URL(uri);
            i = (InputStream) m.getContent();
        } catch (MalformedURLException me) {
            HPLog.e(HPLog.LFP_TAG, "loadImageFromUrl", me);
            return null;
        } catch (IOException ioe) {
            HPLog.e(HPLog.LFP_TAG, "loadImageFromUrl", ioe);
            return null;
        }
        try {
            return readBytes3(i);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != i) {
                    i.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private byte[] readBytes3(InputStream in) throws IOException {
        BufferedInputStream bufin = new BufferedInputStream(in);
        int buffSize = 1024;
        ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);

        // System.out.println("Available bytes:" + in.available());

        byte[] temp = new byte[buffSize];
        int size = 0;
        while ((size = bufin.read(temp)) != -1) {
            out.write(temp, 0, size);
        }
        bufin.close();

        byte[] content = out.toByteArray();
        return content;
    }
}